﻿using OpenCvSharp;
using System;
using System.Collections.Generic;

namespace VNext
{
    public class PhotoCutHelper
    {
        private static Rect _boundingRect;
        private static List<Point> _points = null;
        private static Point _center;

        public static bool IsReady
        {
            get
            {
                return _points != null;
            }
        }

        public static void Init(string pointsText)
        {
            var points = ParsePoints(pointsText);
            if (points != null && points.Count > 0)
            {
                _points = points;
                _boundingRect = Cv2.BoundingRect(_points);
                _center = CalcCenter(_points);
            }
        }

        private static List<Point> ParsePoints(string pointsText)
        {
            var points = new List<Point>();

            if (!string.IsNullOrEmpty(pointsText))
            {
                var items = pointsText.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
                foreach (var item in items)
                {
                    var pairs = item.Split(',');
                    if (pairs.Length == 2)
                    {
                        if (int.TryParse(pairs[0].Trim(), out int x) && int.TryParse(pairs[1].Trim(), out int y))
                        {
                            points.Add(new Point(x, y));
                        }
                    }
                }
            }

            return points;
        }

        static Point CalcCenter(List<Point> points)
        {
            var center = new Point();
            foreach (var p in points)
            {
                center += p;
            }
            center = center * (1d / points.Count);
            return center;
        }

        //public static void CropAndCopyPhoto(string photoPath, string destPath)
        //{
        //    Mat src = Cv2.ImRead(photoPath);
        //    Mat mask = GetMaskFlooddFill(src.Size(), _center, _points);
        //    src = new Mat(src, _boundingRect);
        //    Mat roi = new Mat(mask, _boundingRect);
        //    Cv2.CvtColor(roi, roi, ColorConversionCodes.BGR2GRAY);
        //    var dst = new Mat();
        //    Cv2.BitwiseAnd(src, src, dst, roi);
        //    dst.SaveImage(destPath);
        //    dst.Dispose();
        //}

        public static byte[] CutPhoto(string photoPath)
        {
            Mat src = Cv2.ImRead(photoPath);
            Mat mask = GetMaskFlooddFill(src.Size(), _center, _points);
            src = new Mat(src, _boundingRect);
            Mat roi = new Mat(mask, _boundingRect);
            Cv2.CvtColor(roi, roi, ColorConversionCodes.BGR2GRAY);
            var dst = new Mat();
            Cv2.BitwiseAnd(src, src, dst, roi);
            var bytes = dst.ToBytes();
            mask.Dispose();
            roi.Dispose();
            src.Dispose();
            return bytes;
        }

        static Mat GetMaskFlooddFill(OpenCvSharp.Size size, Point center, List<Point> points)
        {
            if (size.Width < _boundingRect.Size.Width || size.Height < _boundingRect.Size.Height)
            {
                size = _boundingRect.Size;
            }

            Mat mask = Mat.Zeros(size, MatType.CV_8UC3);
            mask = DrawROI(mask, Scalar.Red, points);
            var point = new OpenCvSharp.Point(center.X, center.Y);
            Cv2.FloodFill(mask, point, Scalar.Red);
            mask.ConvertTo(mask, MatType.CV_8UC1);
            return mask;
        }

        static Mat DrawROI(Mat src, Scalar color, List<Point> points)
        {
            var img = src.Clone();
            for (var i = 0; i < 4; ++i)
            {
                if (i == 3)
                {
                    Cv2.Line(img, points[3], points[0], color, 1, LineTypes.AntiAlias);
                }
                else
                {
                    Cv2.Line(img, points[i], points[i + 1], color, 1, LineTypes.AntiAlias);
                }
            }
            return img;
        }
    }
}
